package queue

import "sync"

type Queue[T any] struct {
	_queue []T
	_mutex *sync.Mutex
}

func NewQueue[T any]() *Queue[T] {
	return &Queue[T]{
		_queue: make([]T, 0),
		_mutex: &sync.Mutex{},
	}
}

func (q *Queue[T]) Empty() bool {
	return len(q._queue) == 0
}

func (q *Queue[T]) Push(item T) *Queue[T] {
	q._mutex.Lock()
	defer q._mutex.Unlock()

	q._queue = append(q._queue, item)
	return q
}

func (q *Queue[T]) Pop() T {
	q._mutex.Lock()
	defer q._mutex.Unlock()

	value := q._queue[0]
	q._queue = q._queue[1:]
	return value
}

func (q *Queue[T]) Front() T {
	return q._queue[0]
}

func (q *Queue[T]) Back() T {
	return q._queue[len(q._queue)-1]
}

func (q *Queue[T]) Size() int {
	return len(q._queue)
}

func (q *Queue[T]) Length() int {
	return q.Size()
}
